﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
namespace LitTools
{
    /// <summary>
    /// 日志管理
    /// </summary>
    public class LogManager : MonoSingleton<LogManager>
    {
        /// <summary>
        /// 日志文件名
        /// </summary>
        public string LogFileName { get; private set; }
        /// <summary>
        /// 日志文件路径
        /// </summary>
        public string LogFilePath { get; private set; }
        /// <summary>
        /// 是否正在录制
        /// </summary>
        public bool IsRecording { get; private set; }
        /// <summary>
        /// 记录间隔
        /// </summary>
        public float RecordInterval
        {
            get => recordInterval;
            private set
            {
                if (value <= 0.1f)
                {
                    Debug.LogError("record interval should not less than 0.1f");
                }
                else
                {
                    recordInterval = value;
                }
            }
        }

        private float recordInterval = 1f;//记录间隔
        private float lastRecordTime = float.MinValue;//上次记录事件
        private StringBuilder logContent;//记录内容
        private bool isDirty;//脏标记
        private LogFilterGroup filterGroup;//过滤器组
        #region 生命周期
        private void Update()
        {
            if (!IsRecording) return;
            if (isDirty
                && Time.realtimeSinceStartup - lastRecordTime >= recordInterval)
            {
                lastRecordTime = Time.realtimeSinceStartup;
                StreamWriter sw;
                FileInfo fi = new FileInfo(LogFilePath);
                if (!fi.Exists)
                {
                    //创建日志文件
                    sw = fi.CreateText();
                }
                else
                {
                    sw = fi.AppendText();
                }
                sw.Write(logContent);
                sw.Close();
                sw.Dispose();
                isDirty = false;
                logContent.Clear();
            }
        }
        private void OnDestroy()
        {
            Application.logMessageReceived -= OnLogReceived;
        }
        #endregion

        /// <summary>
        /// 开始记录
        /// </summary>
        public void StartRecording(string filterKey = "")
        {
            if (IsRecording)
            {
                Debug.LogError("Recording Already Started");
                return;
            }
            //选择过滤器
            var logConfig = Resources.Load<LogManagerConfig>("LogManagerConfig");
            filterGroup = logConfig.GetFilterGroupByKey(filterKey);

            LogFileName = $"{System.DateTime.Now.Year}_{System.DateTime.Now.Month}_{System.DateTime.Now.Day}"
             + $"#{System.DateTime.Now.Hour}_{System.DateTime.Now.Minute}_{System.DateTime.Now.Second}";
            LogFilePath = Application.persistentDataPath + "/" + LogFileName + ".txt";
            IsRecording = true;
            Application.logMessageReceived += OnLogReceived;
            Debug.Log("LogManager start recording");
        }

        /// <summary>
        /// 停止记录
        /// </summary>
        public void StopRecording()
        {
            IsRecording = false;
        }

        /// <summary>
        /// 关闭日志
        /// </summary>
        public void DisableLog()
        {
            Debug.unityLogger.logEnabled = false;
        }

        /// <summary>
        /// 收到消息
        /// </summary>
        /// <param name="condition"></param>
        /// <param name="stackTrace"></param>
        /// <param name="type"></param>
        private void OnLogReceived(string condition, string stackTrace, LogType type)
        {
            if (logContent == null)
                logContent = new StringBuilder();
            if (filterGroup == null) return;
            if (!filterGroup.PassFilter(condition, type)) return;
            string line = $"[{System.DateTime.Now.ToShortTimeString()}]({type})\"{condition}\" {stackTrace}\n";
            logContent.Append(line);
            isDirty = true;
        }
    }
}